package com.hulushuju.core.net.cookie.okhttp;

import com.hulushuju.core.net.cookie.CookieManager;
import com.hulushuju.core.net.cookie.CookieStore;
import com.hulushuju.core.net.exception.HttpException;
import com.hulushuju.core.net.exception.UnSupportedTypeException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;

import java.net.HttpCookie;
import java.util.*;

/**
 * @Author: Hanjiafeng
 * @Date: 2019-05-29
 * @Desc:
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class OkCookieManagerImpl implements CookieManager {

    private final CookieStore<Cookie> cookieStore = new CookieStore<>();

    @Override
    public List<HttpCookie> getHttpCookies(String name) {
        List<HttpCookie> httpCookieList = new ArrayList<>();
        //以name获取对应的Cookie List
        List<Cookie> cookieList = cookieStore.getByName(name);
        //将OkHttp.Cookie转换成java.net.HttpCookie
        for (Cookie cookie : cookieList) {
            String value = cookie.value();
            HttpCookie httpCookie = new HttpCookie(name, value);
            httpCookie.setDomain(cookie.domain());
            httpCookie.setPath(cookie.path());
            httpCookie.setMaxAge(cookie.expiresAt());
            httpCookieList.add(httpCookie);
        }
        return httpCookieList;
    }

    @Override
    public void setHttpCookies(List<HttpCookie> httpCookies) {
        Map<String, List<Cookie>> nameCookieMap = new HashMap<>(5);
        for (HttpCookie httpCookie : httpCookies) {
            String name = httpCookie.getName();
            List<Cookie> cookieList = nameCookieMap.containsKey(name) ? nameCookieMap.get(name) : new ArrayList<>();
            Cookie cookie = new Cookie.Builder()
                    .name(name)
                    .value(httpCookie.getValue())
                    .domain(httpCookie.getDomain())
                    .path(httpCookie.getPath())
                    .expiresAt(httpCookie.getMaxAge())
                    .build();
            cookieList.add(cookie);
            nameCookieMap.put(name, cookieList);
        }
        //以name为key,统统写入CookieStore
        Set<String> nameSet = nameCookieMap.keySet();
        for (String name : nameSet) {
            cookieStore.putByName(name, nameCookieMap.get(name));
        }

    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T init(Class<T> c) throws HttpException {
        T t;
        if (c.equals(CookieJar.class)) {
            t = (T) new CookieJar() {
                @Override
                public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) {
                    //当list不为null,且里面有cookie
                    if (!Objects.isNull(list) && !list.isEmpty()) {
                        //以host为key,放入Cookie List
                        cookieStore.putByHost(httpUrl.host(), list);

                        //以Cookie name为key,放入Cookie List
                        Map<String, List<Cookie>> nameCookieMap = new HashMap<>(5);
                        //将CookieList以name为key,写入临时Map
                        for (Cookie cookie : list) {
                            String name = cookie.name();
                            List<Cookie> cookieList = nameCookieMap.containsKey(name) ? nameCookieMap.get(name) : new ArrayList<>();
                            cookieList.add(cookie);
                            nameCookieMap.put(name, cookieList);
                        }
                        //以name为key,统统写入CookieStore
                        Set<String> nameSet = nameCookieMap.keySet();
                        for (String name : nameSet) {
                            cookieStore.putByName(name, nameCookieMap.get(name));
                        }
                    }
                }

                @Override
                public List<Cookie> loadForRequest(HttpUrl httpUrl) {
                    //将所有Cookie统统放入Request
                    return cookieStore.cookiesByName();
                }
            };
        } else {
            throw new UnSupportedTypeException("OkHttp实现中的Cookie管理器只支持CookieJar.class");
        }
        return t;
    }
}
